import { Injectable, OnModuleDestroy } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { createClient } from 'redis';

@Injectable()
export class RedisService implements OnModuleDestroy {
  private readonly client: any; // Redis.RedisClientType 在新版本中类型定义可能不同
  private readonly keyPrefix: string;

  constructor(private readonly configService: ConfigService) {
    this.keyPrefix = this.configService.get('redis.keyPrefix', 'nest_base:');
    
    this.client = createClient({
      socket: {
        host: this.configService.get('redis.host', 'localhost'),
        port: this.configService.get('redis.port', 6379),
      },
      password: this.configService.get('redis.password', ''),
      database: this.configService.get('redis.db', 0),
    });

    this.client.connect().catch(console.error);
  }

  /**
   * 设置键值对
   */
  async set(key: string, value: any, ttl?: number): Promise<void> {
    const fullKey = this.getFullKey(key);
    const stringValue = typeof value === 'string' ? value : JSON.stringify(value);
    
    if (ttl) {
      await this.client.setEx(fullKey, ttl, stringValue);
    } else {
      await this.client.set(fullKey, stringValue);
    }
  }

  /**
   * 获取值
   */
  async get<T = any>(key: string): Promise<T | null> {
    const fullKey = this.getFullKey(key);
    const value = await this.client.get(fullKey);
    
    if (!value) return null;
    
    try {
      return JSON.parse(value);
    } catch {
      return value as T;
    }
  }

  /**
   * 删除键
   */
  async del(key: string): Promise<void> {
    const fullKey = this.getFullKey(key);
    await this.client.del(fullKey);
  }

  /**
   * 检查键是否存在
   */
  async exists(key: string): Promise<boolean> {
    const fullKey = this.getFullKey(key);
    const result = await this.client.exists(fullKey);
    return result === 1;
  }

  /**
   * 设置过期时间
   */
  async expire(key: string, ttl: number): Promise<void> {
    const fullKey = this.getFullKey(key);
    await this.client.expire(fullKey, ttl);
  }

  /**
   * 获取剩余过期时间
   */
  async ttl(key: string): Promise<number> {
    const fullKey = this.getFullKey(key);
    return await this.client.ttl(fullKey);
  }

  /**
   * 发布消息
   */
  async publish(channel: string, message: any): Promise<void> {
    const stringMessage = typeof message === 'string' ? message : JSON.stringify(message);
    await this.client.publish(channel, stringMessage);
  }

  /**
   * 订阅频道
   */
  async subscribe(channel: string, callback: (message: any) => void): Promise<void> {
    await this.client.subscribe(channel, (message) => {
      try {
        const parsedMessage = JSON.parse(message);
        callback(parsedMessage);
      } catch {
        callback(message);
      }
    });
  }

  /**
   * 取消订阅
   */
  async unsubscribe(channel: string): Promise<void> {
    await this.client.unsubscribe(channel);
  }

  /**
   * 获取完整的键名
   */
  private getFullKey(key: string): string {
    return `${this.keyPrefix}${key}`;
  }

  /**
   * 获取Redis客户端实例
   */
  getClient(): any { // Redis.RedisClientType 在新版本中类型定义可能不同
    return this.client;
  }

  async onModuleDestroy() {
    await this.client.quit();
  }
} 